#!/usr/bin/env python
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import os

from common import chromium_utils

from master import master_utils
from master import slaves_list
from master.builders_pools import BuildersPools
from master.factory import annotator_factory
from master.factory import remote_run_factory
from master.try_job_http import TryJobHTTP
from master.v8.tools import verify_subdir_slaves

import config
import master_site_config

ActiveMaster = master_site_config.V8TryServer
MAIL_NOTIFIER = True

# This is the dictionary that the buildmaster pays attention to. We also use
# a shorter alias to save typing.
c = BuildmasterConfig = {}
c['status'] = []

####### DATABASE
config.DatabaseSetup(c)

####### CHANGESOURCES
c['change_source'] = []

# Avoid merging requests.
c['mergeRequests'] = lambda *_: False

m_annotator = annotator_factory.AnnotatorFactory(ActiveMaster)

def m_remote_run(recipe, **kwargs):
  return remote_run_factory.RemoteRunFactory(
      active_master=ActiveMaster,
      repository='https://chromium.googlesource.com/chromium/tools/build.git',
      recipe=recipe,
      factory_properties={'path_config': 'kitchen'},
      **kwargs)

# ----------------------------------------------------------------------------
# STAND-ALONE BUILDER DEFINITIONS

c['builders'] = [
  {
    'name': name,
    'factory': m_annotator.BaseFactory('v8'),
    'slavebuilddir': slavebuilddir,
  } for name, slavebuilddir in [
    ('v8_linux_rel_ng', 'linux'),
    ('v8_linux_verify_csa_rel_ng', 'linux_csa'),
    ('v8_linux_avx2_dbg', 'linux'),
    ('v8_linux_nodcheck_rel_ng', 'linux_nodcheck'),
    ('v8_linux_dbg_ng', 'linux'),
    ('v8_linux_noi18n_rel_ng', 'noi18n'),
    ('v8_linux_gc_stress_dbg', 'linux'),
    ('v8_linux_nosnap_rel', 'linux_nosnap'),
    ('v8_linux_nosnap_dbg', 'linux_nosnap'),
    ('v8_linux_gcc_compile_rel', 'linux_gcc'),
    ('v8_linux_gcc_rel', 'linux_gcc'),
    ('v8_linux64_gcc_compile_dbg', 'linux64_gcc'),
    ('v8_linux64_rel_ng', 'linux64'),
    ('v8_linux64_verify_csa_rel_ng', 'linux64_csa'),
    ('v8_linux64_avx2_rel_ng', 'linux64'),
    ('v8_linux64_avx2_dbg', 'linux64'),
    ('v8_linux64_asan_rel_ng', 'asan64'),
    ('v8_linux64_gyp_rel_ng', 'linux64_gyp'),
    ('v8_linux64_msan_rel', 'msan64'),
    ('v8_linux64_sanitizer_coverage_rel', 'sancov_linux64'),
    ('v8_linux64_tsan_rel', 'tsan64'),
    ('v8_linux64_tsan_concurrent_marking_rel_ng', 'tsan64_cm'),
    ('v8_win_dbg', 'win'),
    ('v8_win_compile_dbg', 'win'),
    ('v8_win_rel_ng', 'win'),
    ('v8_win_nosnap_shared_rel_ng', 'win_nosnap_shared'),
    ('v8_win64_dbg', 'win64'),
    ('v8_win64_rel_ng', 'win64'),
    ('v8_mac_rel_ng', 'mac'),
    ('v8_mac_dbg', 'mac'),
    ('v8_mac_gc_stress_dbg', 'mac'),
    ('v8_mac64_rel', 'mac64'),
    ('v8_mac64_dbg', 'mac64'),
    ('v8_mac64_asan_rel', 'mac64_asan'),
    ('v8_linux_arm_rel_ng', 'arm'),
    ('v8_linux_arm_dbg', 'arm'),
    ('v8_linux_arm_armv8a_rel', 'arm'),
    ('v8_linux_arm_armv8a_dbg', 'arm'),
    ('v8_linux_arm64_rel_ng', 'arm64'),
    ('v8_linux_arm64_dbg', 'arm64'),
    ('v8_linux_arm64_gc_stress_dbg', 'arm64'),
    ('v8_linux_mipsel_compile_rel', 'mipsel'),
    ('v8_linux_mips64el_compile_rel', 'mips64el'),
    ('v8_android_arm_compile_rel', 'android_arm'),
  ]
]

# ----------------------------------------------------------------------------
# CHROMIUM BUILDER DEFINITIONS

c['builders'].extend([
  {
    'name': 'v8_linux_chromium_gn_rel',
    'factory': m_remote_run('chromium_trybot'),
  },
  {
    'name': 'v8_android_chromium_gn_dbg',
    'factory': m_remote_run('chromium_trybot'),
  },
  {
    'name': 'v8_linux_blink_rel',
    'factory': m_remote_run('chromium_trybot'),
  },
])

# ----------------------------------------------------------------------------
# NODE.JS BUILDER DEFINITIONS

c['builders'].extend([
  {
    'name': 'v8_node_linux64_rel',
    'factory': m_remote_run('v8/node_integration'),
  },
])

# ----------------------------------------------------------------------------
# PRESUBMIT BUILDER DEFINITION

c['builders'].append(
  {
    'name': 'v8_presubmit',
    'factory': m_annotator.BaseFactory('run_presubmit',
                                       {'repo_name': 'v8', 'runhooks': True}),
  }
)

####### SCHEDULERS

pools = BuildersPools('v8')
pools['v8'].extend([b['name'] for b in c['builders']])

# Configure the Schedulers;
c['schedulers'] = []

last_good_urls = {'v8': ActiveMaster.last_good_url}
code_review_sites = {'v8': ActiveMaster.code_review_site}

c['schedulers'].append(TryJobHTTP(
    name='v8_try_job_http',
    port=ActiveMaster.try_job_port,
    last_good_urls=last_good_urls,
    code_review_sites=code_review_sites,
    pools=pools))

####### TRIGGERED BUILDERS

c['builders'].extend([
  {
    'name': 'v8_linux_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux_verify_csa_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux_nodcheck_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux_dbg_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux_noi18n_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux64_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux64_verify_csa_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux64_avx2_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux64_gyp_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux64_asan_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux64_tsan_concurrent_marking_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux_arm_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_linux_arm64_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_win_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_win_nosnap_shared_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_win64_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
  {
    'name': 'v8_mac_rel_ng_triggered',
    'factory': m_annotator.BaseFactory('v8'),
    'auto_reboot' : False,
    'slavebuilddir': 'swarming',
  },
])

####### BUILDSLAVES

slaves = slaves_list.SlavesList('slaves.cfg', 'V8TryServer')
for builder in c['builders']:
  # Associate the slaves to the builders. The configuration is in slaves.cfg.
  builder['slavenames'] = slaves.GetSlavesName(builder=builder['name'])
  # Sets nextSlave function for slave affinity.
  builder['nextSlave'] = master_utils.PreferredBuilderNextSlaveFuncNG()

# The 'slaves' list defines the set of allowable buildslaves. List all the
# slaves registered to a builder. Remove dupes.
c['slaves'] = master_utils.AutoSetupSlaves(
    c['builders'],
    config.Master.GetBotPassword(),
    preferred_builder_dict=slaves.GetPreferredBuildersDict())

# Make sure everything works together.
master_utils.VerifySetup(c, slaves)

# Make sure subdir slaves don't auto-reboot.
verify_subdir_slaves(c)

####### STATUS TARGETS

# Buildbot master url:
# Must come before AutoSetupMaster().
c['buildbotURL'] = ActiveMaster.buildbot_url

master_utils.AutoSetupMaster(c, ActiveMaster,
                             order_console_by_time=True,
                             public_html='../master.chromium/public_html',
                             templates=['./templates',
                                        '../master.chromium/templates'])

if MAIL_NOTIFIER:
  # Add a dumb MailNotifier first so it will be used for BuildSlave with
  # notify_on_missing set when they go missing.
  from buildbot.status import mail
  c['status'].append(mail.MailNotifier(
      fromaddr=ActiveMaster.from_address,
      builders=[],
      relayhost=config.Master.smtp,
      lookup=master_utils.UsersAreEmails()))

  # Try job result emails.
  from master.try_mail_notifier import TryMailNotifier
  c['status'].append(TryMailNotifier(
      fromaddr=ActiveMaster.from_address,
      reply_to=ActiveMaster.reply_to,
      subject='try %(result)s for %(reason)s @ r%(revision)s',
      mode='all',
      relayhost=config.Master.smtp,
      lookup=master_utils.UsersAreEmails()))

# Keep last try jobs, the default is too low. Must keep at least a few days
# worth of try jobs.
c['buildHorizon'] = 2000
c['logHorizon'] = 2000
# Must be at least 2x the number of slaves.
c['eventHorizon'] = 200
# Adjust the buildCaches to be 3x the number of slaves per builder.
c['autoBuildCacheRatio'] = 3

####### PROJECT IDENTITY

c['projectName'] = ActiveMaster.project_name
c['projectURL'] = config.Master.project_url
